package com.kool.kadmin.common.intercept;

import com.alibaba.fastjson.JSONObject;
import com.kool.kadmin.common.cache.CacheRepo;
import com.kool.kadmin.common.cache.CacheRepoFactory;
import com.kool.kadmin.common.constant.CacheRepoTypeEnum;
import com.kool.kadmin.common.context.ReqContext;
import com.kool.kadmin.common.util.HttpUtil;
import com.kool.kadmin.common.util.SecurityUtil;
import com.kool.kadmin.common.util.StringUtil;
import com.kool.kadmin.common.cache.TokenVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

/**
 * 后台管理接口拦截器
 *
 * @author: luyu
 * @create: 2019/02/02 13:32
 */
@Slf4j(topic = "REQUEST")
@Component
public class GlobalInterceptor implements HandlerInterceptor {
    @Value("${common.cache_repo}")
    private String cacheRepoType;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        //客户端
        String client = request.getHeader("client");
        //ip
        String ip = HttpUtil.getIpAdrress(request);
        //请求uri
        String uri = request.getRequestURI();
        //请求url
        String url = request.getRequestURL().toString();
        //请求id
        String reqId = request.getHeader("req-id");
        //请求时间
        String reqTime = request.getHeader("req-time");
        //令牌
        String token = request.getHeader("x-token");
        //用户id
        String userId = request.getHeader("user-id");
        //用户登录名
        String loginName = request.getHeader("login-name");
        //签名
        String signature = request.getHeader("signature");
        //测试
        String test = request.getHeader("x-test");
        String requestBody = null;
        //请求类型
        String method = request.getMethod();
        //请求编码
        String charEncoding = request.getCharacterEncoding();
        if (method.equalsIgnoreCase("POST")) {
            try {
                InputStream input = request.getInputStream();
                ByteArrayOutputStream baos = InterceptorHelper.cloneInputStream(input);
                if (charEncoding == null) {
                    charEncoding = "UTF-8";
                }
                requestBody = new String(baos.toByteArray(), charEncoding);

            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }

        // 请求日志
        JSONObject logs = new JSONObject();
        logs.put("client", client);
        logs.put("ip", ip);
        logs.put("uri", uri);
        logs.put("url", url);
        logs.put("reqId", reqId);
        logs.put("reqTime", reqTime);
        logs.put("token", token);
        logs.put("userId", userId);
        logs.put("loginName", loginName);
        logs.put("signature", signature);
        if (handler instanceof HandlerMethod) {
            logs.put("Controller", ((HandlerMethod) handler).getBean().getClass().getName());
            logs.put("Method", ((HandlerMethod) handler).getMethod().getName());
        }
        logs.put("QueryString", request.getQueryString());
        logs.put("RequestMethod", method);
        logs.put("Params", request.getParameterMap());
        logs.put("requestBody", requestBody);
        log.info(logs.toJSONString());

        //开发测试用
        if (StringUtil.isNotEmpty(test)) {
            ReqContext.setUser(0L, "测试号");
            //跳过验签
            return true;
        }

        //登录验证、验签
        if (StringUtil.isEmpty(userId) || StringUtil.isEmpty(token)) {
            response.setStatus(401);
            return false;
        }
        CacheRepo cacheRepo = CacheRepoFactory.getCacheRepo(cacheRepoType);
        if (!cacheRepo.isContain(Long.valueOf(userId), token)) {
            response.setStatus(401);
            return false;
        }
        //验签 签名=md5(请求时间+请求id+令牌)
        StringBuffer sbSignature = new StringBuffer();
        sbSignature.append(reqTime).append(reqId).append(token);
        String vSignature = SecurityUtil.sha(sbSignature.toString());

        if (signature == null || !signature.equals(vSignature)) {
            response.setStatus(401);
            return false;
        }

        //放请求上下文
        ReqContext.setUser(Long.parseLong(userId), loginName);
        ReqContext.setToken(token);

        //刷新token失效时间
        TokenVo tokenVo = new TokenVo();
        tokenVo.setId(Long.parseLong(userId));
        tokenVo.setToken(token);
        tokenVo.setCreatedTime(new Date());
        tokenVo.setLoginName(loginName);
        cacheRepo.putToken(Long.parseLong(userId), tokenVo);
        return true;
    }

}
